
namespace Mulala.Cavan.Presentation.Seedwork
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using Mulala.Cavan.Core.Extension;
    using Mulala.Cavan.Core.Message;

    /// <summary>
    ///     The FactoryProvider instantiates the IFactory class 
    ///     to be the application only object creator
    /// </summary>
    public class FactoryProvider
    {
        #region Singleton
        // beforefieldinit off
        // see: http://www.yoda.arachsys.com/csharp/singleton.html

        /// <summary>
        ///     Gets the current factory
        /// </summary>
        /// <value>The current.</value>
        public static IFactory Factory
        {
            get { return Instance.Current; }
        }

        // see: http://www.yoda.arachsys.com/csharp/beforefieldinit.html

        static class Instance
        {
            // beforefieldinit off

            internal static readonly IFactory Current = CreateFactory();

            /// <summary>
            ///     Creates the factory (i.e. instatiates it)
            /// </summary>
            /// <returns></returns>
            static IFactory CreateFactory()
            {
                var type = Type.GetType(FactoryClass ?? string.Empty) ?? typeof(DefaultFactory);
                if (type.Is())
                {
                    var factory = Activator.CreateInstance(type) as IFactory;
                    if (factory.Is())
                    {
                        return factory;
                    }
                }
                return new DefaultFactory();
            }
        }
        #endregion

        #region CreateInstance<T>
        /// <summary>
        ///     Creates the instance.
        /// </summary>
        /// <returns></returns>
        public static T CreateInstance<T>(IList<AppMessage> messages = null)
        {
            return Factory.CreateInstance<T>(messages);
        }

        public static object CreateInstance(Type type, IList<AppMessage> messages = null)
        {
            return Factory.CreateInstance(type, messages);
        }

        //public static object CreateInstance(string typeName, IList<Message> messages = null)
        //{
        //    return Factory.CreateInstance(typeName, messages);
        //}
        #endregion

        #region properties
        /// <summary>
        ///     if this value is <c>null</c>, the app settings key "FactoryProvider"
        ///     is used. NUnit or other code may set this property to some other value.
        ///     This has to be done before the first call to the factory is made!
        /// </summary>
        public static string FactoryClass { get; set; }
        #endregion properties
    }
}